package com.rightsidetech.http.controller.storeApp.sign;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.rightsidetech.commom.base.ResponseData;
import com.rightsidetech.commom.enums.CodeIdEnum;
import com.rightsidetech.commom.enums.SysSignEnum;
import com.rightsidetech.http.aspect.Log;
import com.rightsidetech.http.aspect.Token;
import com.rightsidetech.http.base.BaseController;
import com.rightsidetech.system.dtos.response.store.StoreSignAppResp;
import com.rightsidetech.system.entity.SysRuleSignIntegral;
import com.rightsidetech.system.entity.store.SysStoreAccountInfo;
import com.rightsidetech.system.entity.store.SysStoreInfo;
import com.rightsidetech.system.entity.store.SysStoreIntegralRecord;
import com.rightsidetech.system.service.SysRuleSignIntegralService;
import com.rightsidetech.system.service.SysStoreInfoService;
import com.rightsidetech.system.service.SysStoreIntegralService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shenyu.client.springmvc.annotation.ShenyuSpringMvcClient;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/storeApp/sign")
@ShenyuSpringMvcClient(path = "/storeApp/sign/**")
@Api(tags = "门店签到相关")
public class SysStoreSignController extends BaseController {

    @Resource
    private SysRuleSignIntegralService sysRuleSignIntegralService;
    @Resource
    private SysStoreIntegralService sysStoreIntegralService;
    @Resource
    private SysStoreInfoService sysStoreInfoService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    private static final String CYCLE_KEY = "STORE:CYCLE:ID:";
    private static final String STATUS_KEY = "STORE:STATUS:ID:";

    @Log
    @Token
    @GetMapping("/status")
    @ApiOperation("获取签到规则")
    public ResponseData<StoreSignAppResp> getStatus(){
        SysRuleSignIntegral rule = sysRuleSignIntegralService.selectByEnum(SysSignEnum.CYCLE);
        SysRuleSignIntegral init = sysRuleSignIntegralService.selectByEnum(SysSignEnum.INIT_INTEGRAL);
        SysRuleSignIntegral even = sysRuleSignIntegralService.selectByEnum(SysSignEnum.EVEN_INTEGRAL);
        StoreSignAppResp resp = new StoreSignAppResp();
        resp.setCycle(rule.getRuleValue().intValue());
        resp.setStatus(rule.getStatus());
        resp.setInitValue(init.getRuleValue());
        resp.setEvenIntegral(even.getRuleValue());
        return ResponseData.success(resp);
    }

    @Log
    @Token
    @GetMapping("/get_sign_day")
    @ApiOperation("获取当前连续多少天")
    public ResponseData<Integer> getSignDay(){
        long storeId = Long.parseLong(getAttribute());
        String cycleKey = CYCLE_KEY + storeId;
        String cycle = stringRedisTemplate.opsForValue().get(cycleKey);
        if(StrUtil.isNotBlank(cycle)){
            SysRuleSignIntegral rule = sysRuleSignIntegralService.selectByEnum(SysSignEnum.CYCLE);
            String[] split = cycle.split(",");
            int day = Integer.parseInt(split[2]);
            if((int)(System.currentTimeMillis()/1000/60/60/24) - day == 1 || (int)(System.currentTimeMillis()/1000/60/60/24) - day == 0){
                int i = Integer.parseInt(split[0]);
                if(i == rule.getRuleValue().intValue()){
                    if(StrUtil.isNotBlank(stringRedisTemplate.opsForValue().get(STATUS_KEY +storeId))){
                        return ResponseData.success(i);
                    }
                }
                if(i > rule.getRuleValue().intValue()){
                    return ResponseData.success(0);
                }
                return ResponseData.success(i);
            }
        }
        return ResponseData.success(0);
    }

    @Log
    @Token
    @GetMapping("/sign_status")
    @ApiOperation("获取今天门店是否签到")
    public ResponseData<Boolean> SignStatus(){
        SysStoreInfo storeInfo = sysStoreInfoService.selectByPrimaryKey(Long.parseLong(getAttribute()));
        if(ObjectUtil.isEmpty(storeInfo)){
            return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(),"未找到登录的门店");
        }
        String statusKey = STATUS_KEY + storeInfo.getId();
        String signStatus = stringRedisTemplate.opsForValue().get(statusKey);
        return ResponseData.success(StrUtil.isNotEmpty(signStatus));
    }

    @Log
    @Token
    @GetMapping("/sign_in")
    @ApiOperation("门店签到")
    public ResponseData<BigDecimal> storeSignIn(){
        SysStoreInfo storeInfo = sysStoreInfoService.selectByPrimaryKey(Long.parseLong(getAttribute()));
        if(ObjectUtil.isEmpty(storeInfo)){
            return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(),"未找到登录的门店");
        }
        SysStoreAccountInfo accountInfo = sysStoreInfoService.selectByStoreId(storeInfo.getId());
        if(ObjectUtil.isEmpty(accountInfo)){
            return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(),"未找到门店对应的账户");
        }
        SysRuleSignIntegral init = sysRuleSignIntegralService.selectByEnum(SysSignEnum.INIT_INTEGRAL);
        if(init.getStatus() == 1){
            return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(),"签到规则已经关闭");
        }
        String statusKey = STATUS_KEY + storeInfo.getId();
        String cycleKey = CYCLE_KEY + storeInfo.getId();
        String signStatus = stringRedisTemplate.opsForValue().get(statusKey);
        if(ObjectUtil.isNotEmpty(signStatus)){
            return ResponseData.fail("今天已经签到过，请勿重复签到");
        }
        stringRedisTemplate.opsForValue().set(statusKey,"1",nextDayTime(), TimeUnit.MILLISECONDS);
        String evenDayStr = stringRedisTemplate.opsForValue().get(cycleKey);
        if(StrUtil.isEmpty(evenDayStr)){
            BigDecimal decimal = initIntegral(storeInfo.getId(), accountInfo, init.getRuleValue(), 1);
            return ResponseData.success(decimal);
        }
        SysRuleSignIntegral cycle = sysRuleSignIntegralService.selectByEnum(SysSignEnum.CYCLE);
        int cycleValue = cycle.getRuleValue().intValue();
        String[] split = evenDayStr.split(",");
        int cycleDay = Integer.parseInt(split[0]);
        if(cycleDay >= cycleValue){
            BigDecimal decimal = initIntegral(storeInfo.getId(), accountInfo, init.getRuleValue(), 1);
            return ResponseData.success(decimal);
        }
        try {
            int day = Integer.parseInt(split[2]);
            if((int)(System.currentTimeMillis()/1000/60/60/24) - day != 1){
                BigDecimal decimal = initIntegral(storeInfo.getId(), accountInfo, init.getRuleValue(), 1);
                return ResponseData.success(decimal);
            }
            BigDecimal decimal = new BigDecimal(split[1]);
            SysRuleSignIntegral even = sysRuleSignIntegralService.selectByEnum(SysSignEnum.EVEN_INTEGRAL);
            decimal = decimal.add(even.getRuleValue());
            initIntegral(storeInfo.getId(),accountInfo,decimal,cycleDay + 1);
            return ResponseData.success(decimal);
        }catch (Exception e){
            e.printStackTrace();
            return ResponseData.fail("签到计算错误");
        }
    }


    private BigDecimal initIntegral(Long storeInfoId, SysStoreAccountInfo accountInfo, BigDecimal value,int cycleDay) {
        String cycleKey = CYCLE_KEY + storeInfoId;
        stringRedisTemplate.opsForValue().set(cycleKey,cycleDay + "," + value.toString() + "," + (System.currentTimeMillis()/1000/60/60/24));
        SysStoreIntegralRecord record = new SysStoreIntegralRecord();
        record.setStoreInfoId(storeInfoId);
        record.setStoreAccountId(accountInfo.getId());
        record.setIntegral(value);
        record.setOperate("签到获取" + value.intValue() + "积分");
        record.setOperateType((byte)2);
        record.setCreatedAt(new Date());
        sysStoreIntegralService.insert(record);
        BigDecimal add = accountInfo.getPoint().add(value);
        accountInfo = new SysStoreAccountInfo();
        accountInfo.setId(record.getStoreAccountId());
        accountInfo.setPoint(add);
        sysStoreInfoService.updateAccountInfo(accountInfo);
        return value;
    }


    private Long nextDayTime(){
        Calendar calendar = Calendar.getInstance();
        calendar.set(calendar.get(Calendar.YEAR),calendar.get(Calendar.MONTH),calendar.get(Calendar.DAY_OF_MONTH),23,59,59);
        return calendar.getTime().getTime() - System.currentTimeMillis();
    }
}
